from PyPDF2 import PdfReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from tqdm import tqdm
from pathlib import Path


class Rammer:
    def __init__(self, input_pdf, font_path, font_size):
        """
        Initialize Rammer with input_pdf, font_path, and font_size.
        Extract the file name and text from the input PDF.
        """
        self.input_pdf_path = input_pdf
        self.font_path = font_path
        self.font_size = font_size

        self.file_name = Path(input_pdf).name
        self.extracted_text = self.extract_text_from_pdf()

    def extract_text_from_pdf(self):
        """Extract text from a PDF and return it as a string."""
        # Open the input PDF file and extract text from each page,
        # then join the extracted text into a single string.
        text = []
        with open(self.input_pdf_path, "rb") as pdf_file:
            pdf_reader = PdfReader(pdf_file)
            for page in tqdm(pdf_reader.pages, desc="Extracting PDF"):
                page_text = page.extract_text() or ""
                text.append(page_text.replace("\n", " "))
        return " ".join(text)

    def reformat_pdf(self):
        """Convert extracted text to a reformatted PDF using a custom font."""
        # Register the custom font and create a canvas to generate the PDF.
        pdfmetrics.registerFont(TTFont("custom_font", self.font_path))
        c = canvas.Canvas(
            self.file_name.replace(".pdf", "_reformatted.pdf"), pagesize=letter
        )
        width, height = letter
        c.setFont("custom_font", self.font_size)

        y_position = height - 40
        lines = self.extracted_text.split("\n")
        # Convert extracted text into reformatted PDF content.
        for line in tqdm(lines, desc="Converting to PDF"):
            words = line.split()
            line = ""
            for word in words:
                # Check if the line width exceeds the page width, and handle page breaks.
                if (
                    c.stringWidth(line + word, "custom_font", self.font_size)
                    <= width - 80
                ):
                    line += word + " "
                else:
                    c.drawString(40, y_position, line.strip())
                    line = word + " "
                    y_position -= self.font_size * 1.2
                    if y_position < 40:
                        c.showPage()
                        c.setFont("custom_font", self.font_size)
                        y_position = height - 40

            c.drawString(40, y_position, line.strip())
            y_position -= self.font_size * 1.2
            if y_position < 40:
                c.showPage()
                c.setFont("custom_font", self.font_size)
                y_position = height - 40
        c.save()